package com.collabscm.waf.app.web.ext;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;

import com.collabscm.waf.app.web.WebUtils;
import com.collabscm.waf.exception.MismatchException;
import com.collabscm.waf.solution.validation.BeanValidationFailure;
import com.collabscm.waf.util.RuntimeContext;
import com.collabscm.waf.vo.FailureResponse;
import com.collabscm.waf.vo.ValidationFailureInfo;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;

/**
 * 验证错误的处理
 *
 * @author Zeng Raoxing
 */
public class ValidationFailtureResult implements Result {
	private static final long serialVersionUID = 1L;

	@Override
	public void execute(ActionInvocation invocation) throws Exception {
		//获得ValidationFailure
		Object o = invocation.getStack().pop();
		if(o instanceof BeanValidationFailure) {
			if(RuntimeContext.getRequestType() != RuntimeContext.AJAX_REQUEST) {
				throw new MismatchException("对于BeanValidation的错误，系统仅支持Ajax方式提交，而如果是其他方式提交，那么需要自定义处理。");
			}
			responseValidationFailure((BeanValidationFailure)o);
		}
	}

	/**
	 * 处理验证失败的错误
	 * 
	 * @param failure
	 */
	protected void responseValidationFailure(BeanValidationFailure failure) {
		FailureResponse fr = fillFailureResponse(failure);
		WebUtils.responseJson(fr);
	}

	/**
	 * 填充验证错误的应答信息
	 * 
	 * @param failure
	 */
	protected FailureResponse fillFailureResponse(BeanValidationFailure failure) {
		FailureResponse fr = new FailureResponse();
		fr.setFailureType(FailureResponse.VALIDATION_FAILURE);
		@SuppressWarnings("unchecked")
		Set<ConstraintViolation<?>> violations = (Set<ConstraintViolation<?>>) failure.getConstraints();
		List<ValidationFailureInfo> failures = new ArrayList<ValidationFailureInfo>();
		for(ConstraintViolation<?> violation: violations) {
			ValidationFailureInfo info = new ValidationFailureInfo();
			info.setName(failure.getRootBean() + "." + violation.getPropertyPath());
			info.setPrompt(violation.getMessage());
			failures.add(info);
		}
		fr.setCause(failures);
		return fr;
	}
	
}
